package com.csii.adhoc.controller.dataunit;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.csii.adhoc.annotation.OperationLog;
import com.csii.adhoc.dataready.TDataCondPo;
import com.csii.adhoc.dataready.TDataCondVo;
import com.csii.adhoc.dataready.TDataNewfun;
import com.csii.adhoc.dataready.TDataNickName;
import com.csii.adhoc.dataready.service.TDataParamService;
import com.csii.adhoc.dataunits.*;
import com.csii.adhoc.dataunits.NumberGroup;
import com.csii.adhoc.dataunits.UnitBase.UnitBasePo;
import com.csii.adhoc.dataunits.UnitBase.UnitBaseVo;
import com.csii.adhoc.dataunits.addcolumn.*;
import com.csii.adhoc.dataunits.service.DataUnitUtils;
import com.csii.adhoc.dataunits.service.DataUnitsService;
import com.csii.result.APIResult;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.logging.log4j.util.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @description 数据组件相关操作
 * @date 20210121
 */
@RestController
@RequestMapping("/dataUnits")
public class DataUnitController {
    private static AtomicInteger atomicInteger = new AtomicInteger(0);
    private final Object lock = new Object();
    private static final Logger log = LoggerFactory.getLogger(DataUnitController.class);
    private static List<String> tokenPool = new ArrayList<>();

    @Autowired
    private DataUnitsService dataUnitsService;
    @Autowired
    private TDataParamService tDataParamService;

    /*
        数据组件新增
        根据前端仪表盘id 和数据集id 新建数据组件
     */
    @RequestMapping(value = "dataUnitAdd", method = RequestMethod.POST)
    public APIResult dataUnitAdd(@RequestBody DataUnitAddRequest req) throws Exception {
        /////////  参数合法性校验
        // 数据集 id
        String dataSetId = req.getDataSetId();
        // 仪表盘 id
        String unitId = req.getUnitId();
        if ((dataSetId == null || "".equals(dataSetId)) || (unitId == null || "".equals(unitId))) {
            throw new IllegalArgumentException("组件 id 和数据集 id 不能为空");
        } else if (dataSetId == null || "".equals(dataSetId)) {
            throw new IllegalArgumentException("数据集 id 不能为空");
        } else if (unitId == null || "".equals(unitId)) {
            throw new IllegalArgumentException("仪表盘 id 不能为空");
        }

        try {
            UnitBasePo unitBasePo = dataUnitsService.selectUnitInfoById(unitId);
            unitBasePo.setModelId(dataSetId);
            dataUnitsService.updateUniteBase(unitBasePo);
        } catch (Exception e) {
            //TODO 跟踪处理各类异常
            e.printStackTrace();
        }

        return APIResult.successResult("");
    }

    /*
        数据组件查询
        根据前端组件 id ，查询组件所有信息
     */
    @RequestMapping(value = "dataUnitQuery", method = RequestMethod.POST)
    public UnitRespone dataUnitQuery(@RequestBody UnitQueryReq req) {
        //
        String dashbordId = req.getDataUnitId();
        List<UnitBaseVo> list = dataUnitsService.queryUnitBaseById(dashbordId);
        UnitRespone unitRespone = new UnitRespone();
//        unitRespone;
        return unitRespone;
    }

    /*
        数据组件修改
        根据前端组件 id ，修改组件所有信息
    */
    @RequestMapping(value = "dataUnitModify", method = RequestMethod.POST)
    public UnitRespone dataUnitModify(@RequestBody UnitModifyReq req) throws Exception {

        int version = atomicInteger.getAndAdd(1);
        System.out.println();
        System.out.println();
        System.out.println();
        System.out.println("####################################################################");
        System.out.println("version_" + version + "    " + req.toString());
        System.out.println("---------------------------------------------------------------------");
        //创建返回对象
        UnitRespone resp = new UnitRespone();
        UnitRespone.Body retBody = resp.new Body();

        // 数据集id
        String modelId = req.getModelId();
        // 组件id
        String unitId = req.getUnitId();
        //所操作表的 tableId,数据集id 和 tableId 二选一即可，为支持可能的扩展，保留二选一形式
        String tableId = req.getTableId();
        //分页信息，当前页号
        Integer pageNum = req.getPageNum();
        //分页信息，每页最大记录数
        Integer pageSize = req.getPageSize();
        // 组件图表类型，具体类型值参见《组件部分开发时说明.md》
        Integer type = req.getType();

        //根据 unitId 获取 数据集 id
        if (modelId == null || "".equals(modelId)) {
            modelId = dataUnitsService.selectModelByUnitId(unitId);
        } else {
            //String modelId2 = dataUnitsService.selectModelByUnitId(unitId);
            //if (modelId2 == null || "".equals(modelId2)) {
            synchronized (lock) {
                dataUnitsService.updateUniteBaseModelId(unitId, modelId);
            }
            //}
        }

        ////////////  前端必输参数合法性校验
        if (unitId == null || "".equals(unitId)) {
            throw new Exception("unitId 不能为空");
        }
        if (((modelId == null || "".equals(modelId)) && (tableId == null || "".equals(tableId)))) {
            throw new Exception("tableId  modelId 至少有一个不能为空");
        }
        if (pageNum == null) {
            pageNum = 1;
            //throw new Exception("pageNum 不能为空");
        }
        if (pageSize == null) {
            pageSize = 10;
            //throw new Exception("pageSize 不能为空");
        }
        if ((tableId == null || "".equals(tableId)) && (modelId != null && !"".equals(modelId))) {
            //临时使用，modelId 从 t_data_from 中来，后面应该改到从 t_data_base 中来
            tableId = dataUnitsService.getTableIdByModelId(modelId);
            if (tableId == null) {
                throw new Exception("无与 modelId 匹配的 tableId");
            }
        }
        if (type == null) {
            /*
            如果 type ==null 表示从仪表盘第一次进入编辑界面，这时前端参数除 unitId 和 tableId
             */
            type = dataUnitsService.getUnitType(unitId);
            if (type == null) {
                throw new Exception("组件图形类型不能为空");
            }
        }

        //存所有返回都要用到的 modelId,用于前端使用
        retBody.setModelId(modelId);
        retBody.setTableId(tableId);

        // 前端所选sql列，当为空时，返回所有，为支持可能存在的扩展，保留
        String[] sqlColumn = req.getSqlColumn();
        // 临时使用的 PageInfo 后端类
        PageInfo pageInfo = new PageInfo(new ArrayList());

        /////////////           维度部分处理
        //指定为当前端输入仅有：维度时，TextFields1 表示行维度，TextFields2 无值
        // 当均有：行维度、列维度和度量时，TextFields1 表示行维度，
        List<TextSelected> textFields1 = req.getTextFields1();
        //指定为当前端输入有：行维度、列维度和度量时，TextFields2 表示列维度，
        List<TextSelected> textFields2 = req.getTextFields2();

        ////  度量部分处理
        List<NumberSelected> numberFields = req.getNumberFields();
         /*
         将 numberFields TextFields1 TextFields1 等信息入库
         此处后端业务逻辑为:当前端传过来的维度信息为空时,表示前端第一次进入到组件,
         这里需要查询当前 dataUnitId(组件id) 存储于数据库的历史维度信息,
         如果前端传过来的维度信息不为空时,则表示前端第二次以后的前端对维度等有修改
         的信息,这时,要删除掉所有当前 dataUnitId 所对应类型(行维度/列维度)信息,
         并将当前维度数据入库
         */
        // 维度度量字段修改时，清除条件筛选
        if ((textFields1 != null && textFields1.size() > 0) || (numberFields != null && numberFields.size() > 0))  {
            dataUnitsService.deleteAllUnitCondition(unitId);
        }

        //1.入库维度信息,3 表示交叉表,维度分为:行维度和列维度，type 为 1 是表示维度或有行维度和列维度时的行维度
        if (textFields1 != null && textFields1.size() > 0) {
            synchronized (lock) {
                //先删除历史数据,再插入新数据
                dataUnitsService.deleteAllUnitKeyByUnitId(unitId, "1");
                dataUnitsService.insertUnitKey(unitId, textFields1, "1");
            }
            //如果前端传输的值为:{numberFields:[{}]}，则清除唯一空单元
            if (textFields1.size() == 0 || textFields1.get(0).getColEn() == null || "".equals(textFields1.get(0).getColEn())) {
                textFields1.clear();
            }
        } else {
            //查询并返回历史数据
            List<UnitKey> unitKeyList = dataUnitsService.getAllUnitKey(unitId, "1");
            System.out.println("version_" + version + "    " + "unitKeyList " + unitKeyList.size());
            for (UnitKey uk : unitKeyList) {
                TextSelected ts = new TextSelected();
                ts.setColEn(uk.getFldEnname());
                ts.setColName(uk.getFldEnname());
                ts.setColType(uk.getType());
                ts.setShowName(uk.getFldCnname());
                ts.setColumnColor("###");
                ts.setColumnSharp(Lists.newArrayList());
                ts.setOrderType("###");
                ts.setSortColName("###");
                ts.setDefSortValues(Lists.newArrayList());
                ts.setGroupType(uk.getCreatedBy());
                ts.setDefGroups(Maps.newHashMap());
                ts.setBeShow(Boolean.valueOf(uk.getFlag()));
                String[] strs = new String[0];
                ts.setOpenedValues(strs);
                textFields1.add(ts);
            }
        }
        //type = 3 表示交叉表,维度分为:行维度和列维度,这时需要将列维度入库，type 为 2 表示列维度
        if (type == 3) {
            if (textFields2 != null && textFields2.size() > 0) {
                synchronized (lock) {
                    //先删除历史数据,再插入新数据
                    dataUnitsService.deleteAllUnitKeyByUnitId(unitId, "2");
                    dataUnitsService.insertUnitKey(unitId, textFields2, "2");
                }
                //如果前端传输的值为:{numberFields:[{}]}，则清除唯一空单元
                if (textFields2.size() == 0 || textFields2.get(0).getColEn() == null || "".equals(textFields2.get(0).getColEn())) {
                    textFields2.clear();
                }
            } else {
                //查询并返回历史数据
                List<UnitKey> unitKeyList = dataUnitsService.getAllUnitKey(unitId, "2");
                System.out.println("version_" + version + "    " + "unitKeyList " + unitKeyList.size());
                for (UnitKey uk : unitKeyList) {
                    TextSelected ts = new TextSelected();
                    ts.setColEn(uk.getFldEnname());
                    ts.setShowName(uk.getFldCnname());
                    ts.setColumnColor("###");
                    ts.setColumnSharp(Lists.newArrayList());
                    ts.setOrderType("###");
                    ts.setSortColName("###");
                    ts.setDefSortValues(Lists.newArrayList());
                    ts.setGroupType("");
                    ts.setDefGroups(Maps.newHashMap());
                    ts.setBeShow(Boolean.valueOf(uk.getFlag()));
                    String[] strs = new String[0];
                    ts.setOpenedValues(strs);
                    textFields2.add(ts);
                }
            }
        }


        if (numberFields != null && numberFields.size() > 0) {
            synchronized (lock) {
                //先删除历史数据,再插入新数据
                dataUnitsService.deleteAllUnitCvgByUnitId(unitId);
                dataUnitsService.insertUnitCvg(unitId, numberFields);
            }
            //如果前端传输的值为:{numberFields:[{}]}，则清除唯一空单元
            if (numberFields.size() == 0 || numberFields.get(0).getColEn() == null || "".equals(numberFields.get(0).getColEn())) {
                numberFields.clear();
            }
        } else {
            //查询并返回历史数据
            List<UnitCvg> unitCvgsList = dataUnitsService.getAllUnitCvg(unitId);
            System.out.println("version_" + version + "    " + "unitCvgsList " + unitCvgsList.size());
            for (UnitCvg unitCvg : unitCvgsList) {
                NumberSelected ns = new NumberSelected();
                ns.setShowName(unitCvg.getFldCnname());
                //前端根据 FunName 判断是汇总计算还是快速计算
                ns.setTotalCalc(unitCvg.getFunName());
                ns.setFastCalc(unitCvg.getFunName());
                // fixme 数据库中尚无该字段，待业务确认
                ns.setDataFormat("");
                // fixme 数据库中尚无该字段，待业务确认
                ns.setBeShow(Boolean.valueOf(ns.isBeShow()));
                ns.setExtConfig1("");
                ns.setExtConfig2("");
                ns.setExtConfig3("");
                ns.setExtConfig4("");
                ns.setColEn(unitCvg.getFldEnname());
                //todo 待业务确认
                ns.setColumnColor("");
                ns.setColumnSharp("");
                numberFields.add(ns);
            }
        }

        ///////////////// 前端带条件部分处理  //////////////////+
        // 前端条件组 vo->dto
        List<TDataCondVo> condListVo = req.getCondition();
        ObjectMapper josnObj = new ObjectMapper();
        String condString = josnObj.writeValueAsString(condListVo);
        List<TDataCondPo> condList = DataUnitsService.conTreeVo2Po(condListVo, modelId);

        // 当前端不带 condition 字段时，后端 req.getCondition() == null ，表示允许返回上一次所有条件，
        // 当前端带 "condition":[] 时，表示前端已经删除掉了所有的 condition，则后端也删除上一次所配置的条件
        if (condListVo != null && condListVo.size() > 0) {
            dataUnitsService.deleteAllUnitCondition(unitId);
            // 前端条件组入库
            synchronized (lock) {
                Map<String,String> map = new HashMap<>();
                map.put("unitId", unitId);
                map.put("cond", condString);
                dataUnitsService.insertUnitCondition(map);
            }
        } else {
            //查询并返回历史数据
            Map<String, String> map = dataUnitsService.getAllCondition(unitId);
            if(map != null && map.size() > 0) {
                String con = map.get("COND");

                JSONArray objects = JSONUtil.parseArray(con);
                condListVo = JSONUtil.toList(objects, TDataCondVo.class);
                condList = DataUnitsService.conTreeVo2Po(condListVo, modelId);
            }
        }

        String combinedSql = "";
        if (condList != null && !CollectionUtils.isEmpty(condList)) {
            combinedSql = " and " + DataUnitUtils.combineSqlWhere(condList);
            System.out.println("条件筛选sql拼接：" + combinedSql);
        }
        //\\\\\\\\\\\\\\\ 前端带条件部分处理结束  \\\\\\\\\\\\\\\\\\

        ///////////////// 过滤组件处理部分        \\\\\\\\\\\\\\\\\\
        String filterSqlWhereCond = dataUnitsService.getFilterUnitCond(unitId);
        ///////////////// 过滤组件处理部分结束  \\\\\\\\\\\\\\\\\\

        //-----------  ”条件筛选“的 where 条件和过滤组件的 where 条件合并为一个 where 条件
        String whereCond = combinedSql;
        if (filterSqlWhereCond != null && !"".equals(filterSqlWhereCond)) {
            whereCond += " " + filterSqlWhereCond;
        }

        /////////        将 echarts 图表所有配置 入库           \\\\\\\\\\\
        /*
        暂时将前端图形存入单一字段中，演示版之后，后期将数据库 t_unit_adn(组件附加信息表)
        删除，同时在后期调前端传入的图表信息表 t_pic_xxx 等的库中。
         */
        String widgets = req.getWidgets();
        if (Strings.isNotBlank(widgets)) {
            dataUnitsService.deleteAllWidgets(unitId, "1");
            synchronized (lock) {
                dataUnitsService.insertAdnInfo(unitId, widgets, "1");
            }
        } else {
            //查询并返回历史数据
            widgets = dataUnitsService.getAllWidgets(unitId, "1");
        }

        // 将组件级 themes 属性入库
        String themes = req.getThemes();
        if (Strings.isNotBlank(themes)) {
            dataUnitsService.deleteAllWidgets(unitId, "2");
            synchronized (lock) {
                dataUnitsService.insertAdnInfo(unitId, themes, "2");
            }
        } else {
            //查询并返回历史数据
            themes = dataUnitsService.getAllWidgets(unitId, "2");
        }

        ////////////        自定义分组处理    //////////////////+
        boolean beDefGroup = false;
        // 处理的最终结果,形成可组合到 Sql 中的字符串
        LinkedHashMap<String, String> groupSqlWhereMap = null;
        //dataUnitsService.handleDefGroup(textFields1);
        for (TextSelected ts : textFields1) {
            String groupType = ts.getGroupType();
            //如果是自定义分组
            if ("def".equals(groupType)) {
                beDefGroup = true;
                //循环处理,保证顺序
                Map<String, List<String>> defGroupsMap = ts.getDefGroups();
                Set<String> everyGroup = defGroupsMap.keySet();
                for (String groupName : everyGroup) {
                    List<String> colValues = defGroupsMap.get(groupName);
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < colValues.size(); i++) {
                        String colValue = colValues.get(i);
                        sb.append(" ")
                                .append(groupName)
                                .append("=")
                                .append(colValue);
                        if (i != colValues.size() - 1) {
                            sb.append(" or");
                        }
                    }
                    //将组合成 where 条件的分组信息存入到 groupSqlWhereArr
                    groupSqlWhereMap.put(groupName, sb.toString());
                }
            }
        }

        ///////////         自定义排序处理    //////////////////+
        boolean beDefSort = false;
        // 处理的最终结果,形成可组合到 Sql 中的字符串
        LinkedHashMap<String, String> sortSqlGroupBy = null;

        ///// 新增列后的查询处理 ---- 将新增后的列组合到查询语句中 ////////
        List<DataNewFld> newFields = dataUnitsService.getNewFieldsByModelId(modelId);


        //分类处理，如果某段一样，可以删除 beak;形成 switch 穿透
        switch (type) {
            //1-分组表
            case 1:
                List<TDataNickName> lists = new ArrayList<>();
                // 构造 head
                LinkedHashMap<String, Object> retMap1 = new LinkedHashMap<>();
                // 查询 oracle 数据库
                Map<String, String> tableHeadInfoMap = null;
                try {
                    tableHeadInfoMap = dataUnitsService.getColumnHeadInfo(tableId);
                    for (String key: tableHeadInfoMap.keySet()) {
                        TDataNickName tDataNickName= new TDataNickName();
                        tDataNickName.setColName(key);
                        tDataNickName.setModelId(modelId);
                        List<TDataNickName> list= tDataParamService.queryExistNickName(tDataNickName);
                        if (list!= null && list.size() > 0 ){
                            lists.add(list.get(0));
                        }
                    }
                } catch (Exception e) {
                    resp.setCode("500");
                    resp.setMessage(e.getMessage());
                    return resp;
                }

                //专用于存放表头 head 信息
                List<Map<String, String>> fieldsList = new ArrayList<>();
                //第一个key 表示 数据行号 rowId
                for (TextSelected ts : textFields1) {
                    //生成表 head 信息，步骤1，根据 维度序号，重组表头 head 信息，进行顺序排序
                    LinkedHashMap<String, String> textFieldsMap = new LinkedHashMap<>();
                    String colEn = ts.getColEn();
                    if (colEn == null) {
                        continue;
                    }
                    //判断前端列的英文名是否带有下划线，如果有下划线，表示为非驼峰命名，则不需要反驼峰命名
                    if (!colEn.contains("_")) {
                        colEn = DataUnitUtils.deCamelCase(colEn);
                    }
                    colEn = colEn.toUpperCase(Locale.ROOT);
                    String showName = ts.getShowName();
                    String comment = (showName != null || !"".equals(showName)) ?
                            showName
                            : tableHeadInfoMap.get(colEn) == null ? colEn : tableHeadInfoMap.get(colEn);
                    textFieldsMap.put("name", DataUnitUtils.camelSqlFieldName(colEn));
                    textFieldsMap.put("value", comment);
                    textFieldsMap.put("colName", humpToUnderscore(DataUnitUtils.camelSqlFieldName(colEn)));
                    textFieldsMap.put("colType", "STRING");
                    for (TDataNickName tDataNickName:lists) {
                        if (getHumpName(tDataNickName.getColName()).equals(colEn)) {
                            textFieldsMap.put("colName", tDataNickName.getColName());
                            textFieldsMap.put("colType", tDataNickName.getColType());
                            break;
                        }
                    }
                    fieldsList.add(textFieldsMap);
                }

                //生成表 head 信息，步骤2，根据 度量序号 重组表头 head 信息，进行顺序排序
                for (NumberSelected ns : numberFields) {
                    //生成表 head 信息，步骤1，根据 维度序号，重组表头 head 信息，进行顺序排序
                    LinkedHashMap<String, String> numberFieldsMap = new LinkedHashMap<>();
                    String colEn = ns.getColEn();
                    if (colEn == null) {
                        continue;
                    }
                    //判断前端列的英文名是否带有下划线，如果有下划线，表示为非驼峰命名，则不需要反驼峰命名
                    if (!colEn.contains("_")) {
                        colEn = DataUnitUtils.deCamelCase(colEn);
                    }
                    colEn = colEn.toUpperCase(Locale.ROOT);
                    String showName = ns.getShowName();
                    String comment = (showName != null || !"".equals(showName)) ?
                            showName
                            : tableHeadInfoMap.get(colEn) == null ? colEn : tableHeadInfoMap.get(colEn);
                    numberFieldsMap.put("name", DataUnitUtils.camelSqlFieldName(colEn));
                    numberFieldsMap.put("value", comment);
                    numberFieldsMap.put("colName", humpToUnderscore(DataUnitUtils.camelSqlFieldName(colEn)));
                    numberFieldsMap.put("colType", "STRING");
                    for (TDataNickName tDataNickName:lists) {
                        if (getHumpName(tDataNickName.getColName()).equals(colEn)) {
                            numberFieldsMap.put("colName", tDataNickName.getColName());
                            numberFieldsMap.put("colType", tDataNickName.getColType());
                            break;
                        }
                    }
                    fieldsList.add(numberFieldsMap);
                }

                //查询并构造 data
                try {
//                    List<NumberSelected> numberArr = new ArrayList<>();
//                    numberArr.addAll(numberFields);
                    System.out.println("version_" + version + "    " + "textFields1: " + textFields1 + "######" + "numberFields: " + numberFields);
                    pageInfo = dataUnitsService.groupByTableQuery(tableId, textFields1, numberFields, condList, groupSqlWhereMap, whereCond, sortSqlGroupBy, pageNum, pageSize);
                } catch (Exception e) {
                    e.printStackTrace();
                    Throwable cause = e.getCause();
                    resp.setCode("200");
                    resp.setMessage("执行 sql 查询是发生错误");
                    resp.setErrorCode("506");
                    resp.setErrorMsg(e.getLocalizedMessage());
                    resp.setDetailErrorMsg(cause == null ? "" : cause.getCause().getMessage());
                    resp.setSuccess(false);
                }

                retBody.setFields(fieldsList);
                List datalist = pageInfo.getList() == null ? new ArrayList() : pageInfo.getList();
                pageInfo.setList(null);
                retBody.setData(datalist);
                retBody.setPage(pageInfo);
                //条件组 po -> vo
                retBody.setCondition(condListVo);
                retBody.setTextFields1(textFields1);
                retBody.setTextFields2(textFields2);
                retBody.setNumberFields(numberFields);
                retBody.setWidgets(widgets);
                retBody.setThemes(themes);
                resp.setBody(retBody);
                break;
            //2-交叉表
            case 2:
                break;
            //3-明细表
            case 3:
//                try {
//                    pageInfo = dataUnitsService.dataQueryPageInfoBySqlColumn(tableId, sqlColumn, combinedSql, pageNum, pageSize);
//                } catch (Exception e) {
//                    Throwable cause = e.getCause();
//                    resp.setCode("506");
//                    resp.setMessage("执行 sql 查询是发生错误");
//                    resp.setErrorCode("506");
//                    resp.setErrorMsg(e.getLocalizedMessage());
//                    resp.setDetailErrorMsg(cause == null ? "" : cause.getCause().getMessage());
//                    resp.setSuccess(false);
//                }
//
//                // 构造 head
//                LinkedHashMap<String, Object> retMap = new LinkedHashMap<>();
//                // fixme 开发时使用 testMap，用完后删除
//                LinkedHashMap<String, String> testMap = new LinkedHashMap<>();
//                testMap.put("41234114", "9874p1u001");
//                testMap.put("41231413", "9874p1u002");
//                testMap.put("41234112", "9874p1u003");
//                testMap.put("41234111", "9874p1u004");
//                retMap.put("head", testMap);
//                // 构造 items
//                retMap.put("items", pageInfo);
//
//                resp.setType(req.getType());
//                resp.setBePagination(true);
//                resp.setData(retMap);
                break;
            //4-自定义图表
            case 4:
                break;
            //5-KPI指标卡
            case 5:
                break;
            //6-颜色表格
            case 6:
                break;
            //7-迷你图
            case 7:
                break;
            //8-热力图
            case 8:
                break;
            //9-分区柱形图
            case 9:
                break;
            //10-堆积柱形图
            case 10:
                break;
            //11-多系列柱形图
            case 11:
                break;
            //12-对比柱状图
            case 12:
                break;
            //13-瀑布图
            case 13:
                break;
            //14-分区折线图
            case 14:
                break;
            //15-多系列折线图
            case 15:
                break;
            //16-折线雷达图
            case 16:
                break;
            //17-范围面积图
            case 17:
                break;
            //18-散点图
            case 18:
                break;
            //19-聚合气泡图
            case 19:
                break;
            //20-饼图
            case 20:
                break;
            //21-玫瑰图
            case 21:
                break;
            //22-地图（区域）
            case 22:
                break;
            //23-地图（点）
            case 23:
                break;
            //24-流向地图
            case 24:
                break;
            //25-热力地图
            case 25:
                break;
            //26-矩形树图
            case 26:
                break;
            //27-词云
            case 27:
                break;
            //28-漏斗图
            case 28:
                break;
            //29-仪表盘
            case 29:
                break;
            default:
        }

        System.out.println("---------------------------------------------------------------------");
        System.out.println("version_" + version + "    " + resp.getBody().toString());
        System.out.println("####################################################################");
        return resp;
    }

    @RequestMapping(value = "tableStructure/{tableId}/{type}/{unitId}", method = RequestMethod.GET)
    public APIResult dataUnitTableColumnType(@PathVariable("tableId") String tableId, @PathVariable("type") String type, @PathVariable("unitId") String unitId, HttpServletRequest request) {
        /*
        文档中的类型：（仅供参考）1-日期，2-区间（数值），3-下拉（文本，数值），4-数值
        1-日期，2-文本，3-数值 (实际前后端的接口交互类型)
         */
        List<TableStructure> list = dataUnitsService.getColumnTypes(tableId, type, unitId);
        return APIResult.successResult(list);
    }

    /**
     * 过滤组件中查看所选列的所有值
     *
     * @param req
     * @return
     */
    @RequestMapping(value = "tableFilter", method = RequestMethod.POST)
    public APIResult tableFilter(@RequestBody UnitModifyReq req) {
        String tableId = req.getTableId();
        String[] sqlColumn = req.getSqlColumn();
        String modelId = req.getModelId();
        //如果前端未传，则默认为首页和每页 10 条数据
        Integer pageNum = req.getPageNum() == null || "".equals(req.getPageNum()) ? 1 : req.getPageNum();
        Integer pageSize = req.getPageSize() == null || "".equals(req.getPageSize()) ? 10 : req.getPageSize();

        if (modelId == null || "".equals(modelId)) {
            if (tableId == null || "".equals(tableId)) {
                return APIResult.failResult("", "tableId 不能为空");
            }
        } else {
            tableId = dataUnitsService.getTableIdByModelId(modelId);
        }

        if (sqlColumn == null || sqlColumn.length == 0) {
            return APIResult.failResult("", "sqlColumn 不能为空");
        }
        PageInfo pageInfo = dataUnitsService.getColumnGroupBy(tableId, req.getSqlColumn(), pageNum, pageSize);
        return APIResult.successResult(pageInfo);
    }

    /**
     * 数据集新增列功能
     */
    @OperationLog("数据集新增列准备")
    @PostMapping("addColumnReady")
    public APIResult addColumnReady(@RequestBody AddColumnReadyReq req) throws Exception {
        List<ColVo> addColVoList = new ArrayList<>();
        Map<String, Object> respMap = new HashMap<>();
        //前端参数校验
        List<Map<String, String>> cols = req.getCols();
        String type = req.getType();
        String nameReq = req.getName() == null ? "" : req.getName();
        String modelId = req.getModelId();
        String id = req.getFieldId();
        if (type == null || "".equals(type)) {
            throw new Exception("类型不能为空");
        }
        if (modelId == null || "".equals(modelId)) {
            throw new Exception("数据集 id 不能为空");
        }

        // 处理列信息
        AddColVo addColVo1 = new AddColVo();
        addColVo1.setId("1");
        addColVo1.setName("日期字段");
        addColVo1.setDescription("");
        addColVo1.setChildren(new ArrayList<ColVo>());

        AddColVo addColVo2 = new AddColVo();
        addColVo2.setId("2");
        addColVo2.setName("文本字段");
        addColVo2.setDescription("");
        addColVo2.setChildren(new ArrayList<ColVo>());

        AddColVo addColVo3 = new AddColVo();
        addColVo3.setId("3");
        addColVo3.setName("数值字段");
        addColVo3.setDescription("");
        addColVo3.setChildren(new ArrayList<ColVo>());

        int i1 = 0;
        int i2 = 0;
        int i3 = 0;

        //如果前端有传列信息过来，则直接使用前端的，如果没有，则要使用所有的列信息
        if (cols != null && cols.size() != 0) {
            for (int i = 0; i < cols.size(); i++) {
                Map<String, String> map = cols.get(i);
                Set<Map.Entry<String, String>> entries = map.entrySet();
                for (Map.Entry<String, String> entry : entries) {
                    String key = entry.getKey();
                    String value = entry.getValue();
                    //1-日期
                    if (value.toLowerCase(Locale.ROOT).contains("date")
                            || value.toLowerCase(Locale.ROOT).contains("timestamp")
                    ) {
                        ColVo subCol = new ColVo();
                        subCol.setName(key);
                        subCol.setEnName(key);
                        subCol.setDescription("");

                        List<ColVo> type1 = addColVo1.getChildren();
                        type1.add(subCol);
                        addColVo1.setCount(++i1);
                    } else
                        //2-文本
                        if (value.toLowerCase(Locale.ROOT).contains("char")) {
                            ColVo sunCol = new ColVo();
                            sunCol.setName(key);
                            sunCol.setEnName(key);
                            sunCol.setDescription("");

                            List<ColVo> type2 = addColVo2.getChildren();
                            type2.add(sunCol);
                            addColVo2.setCount(++i2);
                        } else
                            //3-数值
                            if (value.toLowerCase(Locale.ROOT).contains("number")
                                    || value.toLowerCase(Locale.ROOT).contains("long")
                                    || value.toLowerCase(Locale.ROOT).contains("integer")
                                    || value.toLowerCase(Locale.ROOT).contains("binary_")
                                    || value.toLowerCase(Locale.ROOT).contains("float")
                            ) {
                                ColVo subCol = new ColVo();
                                subCol.setName(key);
                                subCol.setEnName(key);
                                subCol.setDescription("");

                                List<ColVo> type3 = addColVo3.getChildren();
                                type3.add(subCol);
                                addColVo3.setCount(++i3);
                            }
                }
            }
        } else {
            // 查询现有列信息,不含历史新增列
            List<ColumnInfo> colsList = dataUnitsService.getAllColumnByDatasetId(modelId);
            for (int i = 0; i < colsList.size(); i++) {
                ColumnInfo ci = colsList.get(i);
                String dataType = ci.getColumnType() == null ? "" : ci.getColumnType();
                String name = ci.getColumnName() == null ? "" : ci.getColumnName();
                String commit = ci.getColumnCommit() == null ? "" : ci.getColumnCommit();
                //1-日期
                if (dataType.toLowerCase(Locale.ROOT).contains("date")
                        || dataType.toLowerCase(Locale.ROOT).contains("timestamp")
                ) {
                    ColVo subCol = new ColVo();
                    subCol.setEnName(name);
                    subCol.setType(dataType);
                    subCol.setName((commit == null || "".equals(commit)) ? name : commit);
                    subCol.setDescription(commit);

                    List<ColVo> type1 = addColVo1.getChildren();
                    type1.add(subCol);
                    addColVo1.setCount(++i1);
                } else
                    //2-文本
                    if (dataType.toLowerCase(Locale.ROOT).contains("char")) {
                        ColVo subCol = new ColVo();
                        subCol.setEnName(name);
                        subCol.setType(dataType);
                        subCol.setName((commit == null || "".equals(commit)) ? name : commit);
                        subCol.setDescription(commit);

                        List<ColVo> type2 = addColVo2.getChildren();
                        type2.add(subCol);
                        addColVo2.setCount(++i2);
                    } else
                        //3-数值
                        if (dataType.toLowerCase(Locale.ROOT).contains("number")
                                || dataType.toLowerCase(Locale.ROOT).contains("long")
                                || dataType.toLowerCase(Locale.ROOT).contains("integer")
                                || dataType.toLowerCase(Locale.ROOT).contains("binary_")
                                || dataType.toLowerCase(Locale.ROOT).contains("float")
                        ) {
                            ColVo subCol = new ColVo();
                            subCol.setEnName(name);
                            subCol.setType(dataType);
                            subCol.setName((commit == null || "".equals(commit)) ? name : commit);
                            subCol.setDescription(commit);
                            List<ColVo> type3 = addColVo3.getChildren();
                            type3.add(subCol);
                            addColVo3.setCount(++i3);
                        }
            }
        }
        addColVoList.add(addColVo1);
        addColVoList.add(addColVo2);
        addColVoList.add(addColVo3);

        // 处理函数信息
        List<AddColVo> funList = dataUnitsService.getAllFunc(type);

        // 如果 列id 不为空，则表示查询已经创建的列信息，即反查列信息，处理反查列信息
        String colId = req.getFieldId();
        if (colId != null && !"".equals(colId)) {
            DataNewFldVo dataNewFldVo = new DataNewFldVo();
            if (colId != null || !"".equals(colId)) {
                DataNewFld dataNewFld = dataUnitsService.queryAddColumnById(colId);
                dataNewFldVo.setFieldId(dataNewFld.getFieldId());
                dataNewFldVo.setModelId(dataNewFld.getModelId());
                dataNewFldVo.setName(dataNewFld.getColName());
                dataNewFldVo.setShowName(dataNewFld.getShowName());
                dataNewFldVo.setType(dataNewFld.getType());
                dataNewFldVo.setText(dataNewFld.getText());
                dataNewFldVo.setValue1(dataNewFld.getValue1());
                dataNewFldVo.setValue2(dataNewFld.getValue2());
                dataNewFldVo.setValue3(dataNewFld.getValue3());
                dataNewFldVo.setSeqNo(dataNewFld.getSeqNo());
                if (dataNewFld != null || !"".equals(dataNewFld)) {
                    String type1 = (dataNewFld.getType() == null || "".equals(dataNewFld.getType())) ? "" : dataNewFld.getType();
                    switch (type1) {
                        // 公式函数
                        case "1":   // switch 穿透到 case 5
                            // 时间差
                        case "2":   // switch 穿透到 case 5
                            // 获取时间
                        case "3":   // switch 穿透到 case 5

                            // 所有值 - 累计值
                        case "4": // switch 穿透到 case 5
                        case "5":
                            String rule = dataNewFld.getValue1() == null ? "" : dataNewFld.getValue1();
                            // rule = 2 表示 所有值-组内所有值 类型
                            if ("2".equals(rule)) {
                                List<TDataOrd> selects = dataUnitsService.getOrderByType(modelId, nameReq, "1");
                                List<TDataOrd> ordered = dataUnitsService.getOrderByType(modelId, nameReq, "2");

                                List<ColValueOrderVo> selectVo = new ArrayList<>();
                                List<ColValueOrderVo> orderVo = new ArrayList<>();
                                for (int i = 0; i < selects.size(); i++) {
                                    TDataOrd sl = selects.get(i);
                                    ColValueOrderVo vo = new ColValueOrderVo();
                                    vo.setName(sl.getShowName());
                                    vo.setValue(sl.getName());
                                    selectVo.add(vo);
                                }

                                ordered.forEach(sl -> {
                                    ColValueOrderVo vo = new ColValueOrderVo();
                                    vo.setName(sl.getShowName());
                                    vo.setValue(sl.getName());
                                    orderVo.add(vo);
                                });
                                dataNewFldVo.setSelects(selectVo);
                                dataNewFldVo.setOrdered(orderVo);
                            }
                            break;

                        // 累计值 - 所有
                        case "6":
                            String rule2 = dataNewFld.getValue1() == null ? "" : dataNewFld.getValue1();
                            // rule = 1 表示 所有值-组内所有值 类型
                            if ("3".equals(rule2) || "4".equals(rule2)) {
                                List<TDataOrd> selects = dataUnitsService.getOrderByType(modelId, nameReq, "1");
                                List<TDataOrd> ordered = dataUnitsService.getOrderByType(modelId, nameReq, "2");

                                List<ColValueOrderVo> selectVo = new ArrayList<>();
                                List<ColValueOrderVo> orderVo = new ArrayList<>();
                                for (int i = 0; i < selects.size(); i++) {
                                    TDataOrd sl = selects.get(i);
                                    ColValueOrderVo vo = new ColValueOrderVo();
                                    vo.setName(sl.getShowName());
                                    vo.setValue(sl.getName());
                                    selectVo.add(vo);
                                }

                                ordered.forEach(sl -> {
                                    ColValueOrderVo vo = new ColValueOrderVo();
                                    vo.setName(sl.getShowName());
                                    vo.setValue(sl.getName());
                                    orderVo.add(vo);
                                });
                                dataNewFldVo.setSelects(selectVo);
                                dataNewFldVo.setOrdered(orderVo);
                            }
                            break;

                        //排名
                        case "7":
                            dataNewFld.setType("7");
                            respMap.put("subType", "1");
                            // 分组赋值 - 文字
                            TTextGrp textGrp = new TTextGrp();
                            textGrp.setModelId(modelId);
                            textGrp.setId(id);
                            List<TTextGrp> textGroupTemps = dataUnitsService.getTextGrpByModelId(textGrp);
                            List<TextGroup> result = new ArrayList<TextGroup>();
                            Map<String, List<TTextGrp>> map = new HashMap<>();
                            map = textGroupTemps.stream().collect(Collectors.groupingBy(TTextGrp -> TTextGrp.getGroupName()));
                            for (Map.Entry<String, List<TTextGrp>> entry : map.entrySet()) {
                                TextGroup tmp = new TextGroup();
                                tmp.setGroupName(entry.getKey());
                                tmp.setContent(entry.getValue().stream().map(TTextGrp::getValue).collect(Collectors.toList()));
                                result.add(tmp);
                            }
                            for (int i = 0; i < result.size(); i++) {
                                if (result.get(i).getGroupName().equals("未分组") & i != 0) {
                                    Collections.swap(result, i, 0);
                                }
                            }
                            dataNewFldVo.setSubType("1");
                            dataNewFldVo.setTextGroups(result);
                            break;
                        case "8":
                            dataNewFld.setType("7");
                            respMap.put("subType", "2");
                            // 分组赋值 数字 - 自定义
                            NumberGroup dataGrp = new NumberGroup();
                            dataGrp.setModelId(modelId);
                            List<TDataGrp> dataGrps = dataUnitsService.getDataGrpByModelId(dataGrp);
                            List<NumberGroup> result1 = new ArrayList<NumberGroup>();
                            Map<String, List<TDataGrp>> map1 = new HashMap<>();
                            for (TDataGrp grp : dataGrps) {
                                NumberGroup temp = new NumberGroup();
                                temp.setCloseMax(grp.getCloseMax());
                                temp.setCloseMin(grp.getCloseMin());
                                temp.setGroupName(grp.getGroupName());
                                temp.setMax(new BigDecimal(grp.getMax()));
                                temp.setMin(new BigDecimal(grp.getMin()));
                                result1.add(temp);
                            }
                            dataNewFldVo.setSubType("2");
                            dataNewFldVo.setNumberGroups(result1);
                            break;
                        case "9":
                            dataNewFld.setType("7");
                            respMap.put("subType", "3");
                            dataNewFldVo.setSubType("3");
                            break;
                    }
                }
            }
            respMap.put("addedColumn", dataNewFldVo);
        }
        respMap.put("columnInfo", addColVoList);
        respMap.put("functionInfo", funList);
        return APIResult.successResult(respMap);
    }


    @OperationLog("数据集删除新增的列")
    @PostMapping("deleteColumn")
    public APIResult deleteColumn(@RequestBody DeleteColumnReq req) {
        //前端参数校验
        String fieldId = req.getFieldId();
        if (fieldId == null || "".equals(fieldId)) {
            return APIResult.failResult("", "fieldId 不能为空");
        }
        try {
            dataUnitsService.deleteAddedColumnById(fieldId);
        } catch (Exception e) {
            e.printStackTrace();
            return APIResult.failResult("", "fieldId 不存在");
        }
        return APIResult.successResult("");
    }

    /**
     * 数据集新增列，前端点击最后的确认操作后向后台发实质性入库操作
     *
     * @param req
     * @return
     */
    @OperationLog("数据集新增列")
    @PostMapping("addColumn")
    public APIResult addColumn(@RequestBody AddColumnReq req) {

        // 前端参数校验
        String fieldId = req.getFieldId();
        String type = req.getType();
        String colName = req.getName();
        String modelId = req.getModelId();
        String showName = req.getShowName() == null ? "" : req.getShowName();
        String text = req.getText() == null ? "" : req.getText();
        String value1 = req.getValue1() == null ? "" : (String) req.getValue1();
        String value2 = req.getValue2() == null ? "" : (String) req.getValue2();
        String value3 = req.getValue3() == null ? "" : (String) req.getValue3();

        if (colName == null || "".equals(colName)) {
            return APIResult.failResult("", "列名不能为空");
        }
        if (type == null || "".equals(type)) {
            return APIResult.failResult("", "表达式不能为空");
        }
        if (modelId == null || "".equals(modelId)) {
            return APIResult.failResult("", "数据集 id 不能为空");
        }
        DataNewFld dnf = new DataNewFld();
        dnf.setFieldId(fieldId);
        dnf.setModelId(modelId);
        dnf.setColName(colName);
        dnf.setText(text);
        dnf.setShowName(showName);
        String colId = "";
        switch (type) {
            //公式函数,出入库测试通过
            case "1":
                dnf.setType("1");
                dnf.setValue1(value1);
                dnf.setValue2(value2);
                dnf.setValue3(value3);
                colId = dataUnitsService.insertNewFld(dnf);
                break;
            //时间差
            case "2":
                dnf.setType("2");
                dnf.setValue1(value1);
                dnf.setValue2(value2);
                dnf.setValue3(value3);
                colId = dataUnitsService.insertNewFld(dnf);
                break;
            //获取时间
            case "3":
                dnf.setType("3");
                dnf.setValue1(value1);
                dnf.setValue2(value2);
                dnf.setValue3(value3);
                colId = dataUnitsService.insertNewFld(dnf);
                break;
            //所有值-累计值
            case "4":
                dnf.setType("4");
                dnf.setValue1(value1);
                dnf.setValue2(value2);
                dnf.setValue3(value3);
                if (value1 != null && "2".equals(value1)) {
                    //入两次 order 表， 一次为 selects ，一次为 ordered
                    List<ColValueOrderVo> selects = req.getSelects();
                    List<ColValueOrderVo> ordered = req.getOrdered();
                    ArrayList<ColValueOrder> selectsOrders = new ArrayList<>();
                    ArrayList<ColValueOrder> orderedOrders = new ArrayList<>();
                    selects.forEach(sl -> {
                        ColValueOrder colValueOrder = new ColValueOrder();
                        colValueOrder.setType("1");
                        colValueOrder.setColName(sl.getValue());
                        colValueOrder.setShowName(sl.getName());
                        colValueOrder.setModelId(modelId);
                        selectsOrders.add(colValueOrder);
                    });

                    ordered.forEach(or -> {
                        ColValueOrder colValueOrder = new ColValueOrder();
                        colValueOrder.setType("2");
                        colValueOrder.setColName(or.getValue());
                        colValueOrder.setShowName(or.getName());
                        colValueOrder.setModelId(modelId);
                        orderedOrders.add(colValueOrder);
                    });

                    dataUnitsService.insertOderTable(selectsOrders, dnf, "1");
                    dataUnitsService.insertOderTable(orderedOrders, dnf, "2");
                }
                colId = dataUnitsService.insertNewFld(dnf);
                break;
            //所有值-组内所有值
            case "5":
                dnf.setType("5");
                dnf.setValue1(value1);
                dnf.setValue2(value2);
                dnf.setValue3(value3);
                if (value1 != null && "2".equals(value1)) {
                    //入两次 order 表， 一次为 selects ，一次为 ordered
                    List<ColValueOrderVo> selects = req.getSelects();
                    List<ColValueOrderVo> ordered = req.getOrdered();
                    ArrayList<ColValueOrder> selectsOrders = new ArrayList<>();
                    ArrayList<ColValueOrder> orderedOrders = new ArrayList<>();
                    selects.forEach(sl -> {
                        ColValueOrder colValueOrder = new ColValueOrder();
                        colValueOrder.setType("1");
                        colValueOrder.setColName(sl.getValue());
                        colValueOrder.setShowName(sl.getName());
                        colValueOrder.setModelId(modelId);
                        selectsOrders.add(colValueOrder);
                    });

                    ordered.forEach(or -> {
                        ColValueOrder colValueOrder = new ColValueOrder();
                        colValueOrder.setType("2");
                        colValueOrder.setColName(or.getValue());
                        colValueOrder.setShowName(or.getName());
                        colValueOrder.setModelId(modelId);
                        orderedOrders.add(colValueOrder);
                    });

                    dataUnitsService.insertOderTable(selectsOrders, dnf, "1");
                    dataUnitsService.insertOderTable(orderedOrders, dnf, "2");
                }
                colId = dataUnitsService.insertNewFld(dnf);
                break;
            //排名/组内 排名/组内升降序
            case "6":
                dnf.setType("6");
                dnf.setValue1(value1);
                dnf.setValue2(value2);
                dnf.setValue3(value3);
                if (value1 != null && ("3".equals(value1) | "4".equals(value1))) {
                    //入两次 order 表， 一次为 selects ，一次为 ordered
                    List<ColValueOrderVo> selects = req.getSelects();
                    List<ColValueOrderVo> ordered = req.getOrdered();
                    ArrayList<ColValueOrder> selectsOrders = new ArrayList<>();
                    ArrayList<ColValueOrder> orderedOrders = new ArrayList<>();
                    selects.forEach(sl -> {
                        ColValueOrder colValueOrder = new ColValueOrder();
                        colValueOrder.setType("1");
                        colValueOrder.setColName(sl.getValue());
                        colValueOrder.setShowName(sl.getName());
                        colValueOrder.setModelId(modelId);
                        selectsOrders.add(colValueOrder);
                    });

                    ordered.forEach(or -> {
                        ColValueOrder colValueOrder = new ColValueOrder();
                        colValueOrder.setType("2");
                        colValueOrder.setColName(or.getValue());
                        colValueOrder.setShowName(or.getName());
                        colValueOrder.setModelId(modelId);
                        orderedOrders.add(colValueOrder);
                    });

                    dataUnitsService.insertOderTable(selectsOrders, dnf, "1");
                    dataUnitsService.insertOderTable(orderedOrders, dnf, "2");
                }
                colId = dataUnitsService.insertNewFld(dnf);
                break;
            case "7":
                dnf.setType("7");
                dnf.setValue1(value1);
                dnf.setValue2(value2);
                dnf.setValue3(value3);
                String subType = req.getSubType() == null ? "" : req.getSubType();

                if (subType != null && "1".equals(subType)) {
                    dnf.setType("7");
                    colId = dataUnitsService.insertNewFld(dnf);
                    dnf.setFieldId(colId);
                    List<TextGroup> textGroups = req.getTextGroups();
                    dataUnitsService.insertTextGrp(textGroups, dnf);
                } else if (subType != null && "2".equals(subType)) {
                    dnf.setType("8");
                    colId = dataUnitsService.insertNewFld(dnf);
                    dnf.setFieldId(colId);
                    List<NumberGroup> numberGroups = req.getNumberGroups();
                    numberGroups.forEach(ng -> {
                        ng.setModelId(modelId);
                    });
                    dataUnitsService.insertNumberGrp(numberGroups, dnf);
                } else if (subType != null && "3".equals(subType)) {
                    dnf.setType("9");
                    colId = dataUnitsService.insertNewFld(dnf);
                }
                break;
        }

        Map<Object, Object> map = new HashMap<>();
        map.put("type", type);
        map.put("fieldId", colId);
        map.put("name", colName);
        map.put("modelId", modelId);
        return APIResult.successResult(map);
    }

    /**
     * 新增列中的中间接口-- 表达式合法性判断
     *
     * @param expReq
     * @return
     */
    @OperationLog("数据集表达式合法性判断")
    @PostMapping("expression")
    public APIResult expression(@RequestBody ExpressionReq expReq) {

        //前端参数校验
        String exp = expReq.getExp();
        String modelId = expReq.getModelId();
        if (exp == null || "".equals(exp)) {
            return APIResult.failResult("", "表达式字串不能为空");
        }
        if (modelId == null || "".equals(modelId)) {
            return APIResult.failResult("", "数据集 id 不能为空");
        }

        ///// 正则定义与处理
        //Java 规则的方法函数名正则表达式
        String reg2 = "[_$a-zA-Z]+[_$0-9a-zA-Z]*";
        // 函数体的正则表达式,匹配 sum(,,,)
        String funcCallReg = "\\w+\\([^()]*\\)";
        //处理后的表达式
        String replacedStr = "";

        //key: 函数名 value:参数个数
        List<FuncTempObject> funNameList = new ArrayList<>();
        //从函数表中查询当前所有的可用函数，并将前端传过来的函数名与现有函数库的函数进行匹配，如果不匹配，则报函数名不正确错误
        //如果可用，则以根据返回类型，模拟一个值作为表达式的计算值，参与表达式的计算，用以判断表达式的合法性
        //缓存函数到内存
        List<TDataNewfun> tDataFuncLis = FunctionCache.list;
        if (tDataFuncLis == null) {
            tDataFuncLis = dataUnitsService.getAllTDataFunc();
            FunctionCache.list = tDataFuncLis;
        }

        Pattern p = Pattern.compile(funcCallReg);
        Matcher propsMatcher = p.matcher(exp);
        //StringBuffer sb = new StringBuffer();
        while (propsMatcher.find()) {
            int startIndex = propsMatcher.start(); // index of start
            int endIndex = propsMatcher.end(); // index of end + 1
            String funcBody = exp.substring(startIndex, endIndex);
            //拆解函数名
            Pattern p2 = Pattern.compile(reg2);
            Matcher matcher = p2.matcher(funcBody);
            if (matcher.find()) {
                int startIndex2 = matcher.start(); // index of start
                int endIndex2 = matcher.end(); // index of end + 1
                String funcName = funcBody.substring(startIndex2, endIndex2);
                FuncTempObject funcTempObject = new FuncTempObject();
                funcTempObject.setFuncBody(funcBody);
                funcTempObject.setFuncName(funcName);
                funNameList.add(funcTempObject);

                //函数名是不是不存在于 函数信息表中，默认为不存在
                boolean beNotFuncExists = true;

                //匹配现有函数
                for (TDataNewfun tDataFuncLi : tDataFuncLis) {
                    String funcBodyReplaced = "";
                    if (funcName.equals(tDataFuncLi.getFunName() == null ? "" : tDataFuncLi.getFunName().trim())) {
                        switch (tDataFuncLi.getRetType().intValue()) {
                            case 1:
                                //propsMatcher.appendReplacement(sb, "1");
                                funcBodyReplaced = funcBody.replaceAll("\\(", "\\\\(").replaceAll("\\)", "\\\\)");
                                replacedStr = exp.replaceAll(funcBodyReplaced, "1");
                                break;
                            case 2:
                                //propsMatcher.appendReplacement(sb, "\"test\"");
                                funcBodyReplaced = funcBody.replaceAll("\\(", "\\\\(").replaceAll("\\)", "\\\\)");
                                replacedStr = exp.replaceAll(funcBodyReplaced, "\"test\"");
                                break;
                            case 3:
                                //propsMatcher.appendReplacement(sb, new Date().toString());
                                funcBodyReplaced = funcBody.replaceAll("\\(", "\\\\(").replaceAll("\\)", "\\\\)");
                                replacedStr = exp.replaceAll(funcBodyReplaced, "\"" + new Date().toString() + "\"");
                                break;
                        }
                        //表示该函数名存在于 函数信息表中
                        beNotFuncExists = false;
                        break;
                    }
                }
                if (beNotFuncExists) {
                    return APIResult.failResult("", "该函数不合法");
                }
//
//                //参数合法性校验第二步，如果函数存在于函数信息表，则将该函数级一个 select 函数表达式1，函数表达式2,... from modelId对应的表，再次进行校验
//                boolean beValid = dataUnitsService.checkFuncValid(funcBody, modelId);
//                if (!beValid) {
//                    return APIResult.failResult("", "表达式不合法");
//                }
            }
        }

        //表达式合法性计算
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("js");
        try {
            Object eval = engine.eval(replacedStr);
        } catch (ScriptException e) {
            e.printStackTrace();
            return APIResult.failResult("", "表达式不合法");
        }
        return APIResult.successResult("表达式合法");
    }

    /**
     * 新增列的中间接口 -- 数据集数字分组计算，即将数值域计算其最大最小值，并分成默认5段返回给前端
     *
     * @param rangeReq
     * @return
     */
    @OperationLog("数据集数字分组计算")
    @PostMapping("range")
    public APIResult range(@RequestBody RangeReq rangeReq) {
        String fieldName = rangeReq.getFieldName();
        String modelId = rangeReq.getModelId();
        if (modelId == null || "".equals(modelId)) {
            return APIResult.failResult("", "数据集id不能为空");
        }
        if (fieldName == null || "".equals(fieldName)) {
            return APIResult.failResult("", "数值型的列名不能为空");
        }

        Map<String, Object> resp = dataUnitsService.getIntColumnInfo(modelId, fieldName);
        return APIResult.successResult(resp);
    }

    /**
     * 新增列中间接口 -- 数据集中列为字符串类型时，返回其所有的值域
     *
     * @param rangeReq 前端请求
     * @return 所有值域
     */
    @OperationLog("数据集字符分组计算")
    @PostMapping("data")
    public APIResult data(@RequestBody RangeReq rangeReq) {
        String fieldName = rangeReq.getFieldName();
        String datasetId = rangeReq.getModelId();
        if (datasetId == null || "".equals(datasetId)) {
            return APIResult.failResult("", "数据集id不能为空");
        }
        if (fieldName == null || "".equals(fieldName)) {
            return APIResult.failResult("", "字符型的列名不能为空");
        }

        Integer pageNum = rangeReq.getPageNum();
        Integer pageSize = rangeReq.getPageSize();

        Map<String, Object> resp = dataUnitsService.getIntColumnInfo2(datasetId, fieldName, pageNum, pageSize);

        return APIResult.successResult(resp);
    }

    /**
     * 新增列中间接口 -- 数据集文本字段模糊搜索
     *
     * @param searchReq 前端请求参数
     * @return 返回搜索出的值域
     */
    @OperationLog("数据集模糊搜索")
    @PostMapping("search")
    public APIResult search(@RequestBody SearchReq searchReq) {
        String fieldName = searchReq.getFieldName();
        String datasetId = searchReq.getDatasetId();
        String keyword = searchReq.getKeyword();
        if (datasetId == null || "".equals(datasetId)) {
            return APIResult.failResult("", "数据集id不能为空");
        }
        if (fieldName == null || "".equals(fieldName)) {
            return APIResult.failResult("", "字符型列名不能为空");
        }
        if (keyword == null || "".equals(keyword)) {
            return APIResult.failResult("", "待搜索的关键字不能为空");
        }

        Map<String, Object> resp = dataUnitsService.getIntColumnInfo3(datasetId, fieldName, keyword);
        return APIResult.successResult(resp);
    }

    @OperationLog("新增列后根据列id返显配置")
    @GetMapping("queryAddColumn/{colId}")
    public APIResult queryAddColumn(@PathVariable("colId") String colId) {
        //参数合法性校验
        if (colId == null || "".equals(colId)) {
            return APIResult.failResult("", "colId 不能为空");
        }
        DataNewFld tDataFldPo = dataUnitsService.queryAddColumnById(colId);
        if (tDataFldPo == null) {
            return APIResult.failResult("", "无数据");
        } else {
            String type = (tDataFldPo.getType() == null || "".equals(tDataFldPo.getType())) ? "" : tDataFldPo.getType();
            switch (type) {
                // 公式函数
                case "1":
                    // 时间差
                case "2":
                    // 获取时间
                case "3":
                    break;
                // 所有值 - 累计值
                case "4":
                    break;
                // 所有值 - 组内所有值
                case "5":
                    break;
                // 累计值 - 所有
                case "6":
                    break;
                //排名
                case "7":
                    break;
                case "8":
                    break;
                //分组赋值 文字
                case "9":
                    break;
                // 分组赋值 - 自动
                case "10":
                    break;
            }
        }
        return APIResult.successResult("");
    }

    @OperationLog("获取 token")
    @GetMapping("getToken")
    public String getToken() {
        String uuid = DataUnitUtils.uuid();
        tokenPool.add(uuid);
        return uuid;
    }

    @OperationLog("数据集新增列准备")
    @PostMapping("queryAllNewFld")
    public APIResult queryAllNewFld(@RequestBody AddColumnReadyReq req) throws Exception {
        //前端参数校验
        String modelId = req.getModelId();
        if (modelId == null || "".equals(modelId)) {
            return APIResult.failResult("", "modelId 不能为空");
        } else {
            List<DataNewFld> list = dataUnitsService.queryAllNewFldByModelId(modelId);
            List<Map> maps = new ArrayList<>();
            list.forEach(l -> {
                Map<String, String> map = new HashMap<>();
                map.put("name", l.getColName());
                map.put("fieldId", l.getFieldId());
                map.put("text", l.getText());
                map.put("type", l.getType());
                map.put("column", l.getValue1());
                maps.add(map);
            });
            return APIResult.successResult(maps);
        }
    }

    /**
     * 测试性接口--新增列函数功能数据库操作验证，增删改查
     */
    @OperationLog("新增列函数功能数据库操作验证")
    @PostMapping("func")
    public APIResult funcText() {
        NumberGroup ng = new NumberGroup();
        ArrayList<NumberGroup> ns = new ArrayList<>();
        ng.setId("1234");
        ng.setGroupName("134334");
        ng.setMin(new BigDecimal("1324"));
        ng.setMax(new BigDecimal("99999"));
        ng.setValid("1");
        ns.add(ng);
        return APIResult.successResult(ns);
    }

    /**
     * 数据库命名转换成驼峰命名
     * @param dbFiled
     * @return
     */
    public static String getHumpName(String dbFiled) {
        return StrUtil.toCamelCase(dbFiled);
    }
    public static String humpToUnderscore(String str) {
        if (str == null || str.length() == 0) {
            return "";
        }
        char[] chars = str.toCharArray();
        StringBuilder sb = new StringBuilder();
        for (char c : chars) {
            if (c >= 'A' && c <= 'Z') {
                sb.append("_");
            }
            sb.append(c);
        }
        return sb.toString().toUpperCase();
    }

}
